﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;

using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;

namespace ScreenShark
{
    public partial class MainForm : Form
    {
        private GlobalHotkey fPrintScreen;
        private GlobalHotkey fAltPrintScreen;


        private SplashForm fSplashForm;
        private List<PreviewForm> fPreviewFormList = new List<PreviewForm>();

        public MainForm()
        {
            InitializeComponent();
            InitializeApplication();
            CreateHotkeys();
        }

        public bool RunOnStartup
        {
            get { return startupCheckBox.Checked; }
            set { startupCheckBox.Checked = value; }
        }

        public string OpenWith
        {
            get { return openWithTextBox.Text; }
            set { openWithTextBox.Text = value; }
        }

        public String OutputDirectory
        {
            get { return folderTextBox.Text; }
            set { folderTextBox.Text = value; }
        }

        public ImageCodecInfo CodecInfo
        {
            get { return imageFormatsComboBox.SelectedItem as ImageCodecInfo; }
            set { imageFormatsComboBox.SelectedItem = value; }
        }

        public bool PreviewBeforeSave
        {
            get { return previewCheckBox.Checked; }
            set { previewCheckBox.Checked = value; }
        }

        public int JpegQuality { get; set; }

        public PostCaptureAction PostCaptureAction
        {
            get
            {
                if (doNothingRadioButton.Checked)
                    return PostCaptureAction.DoNothing;
                else if (goToRadioButton.Checked)
                    return PostCaptureAction.GoToLastScreenshot;

                return PostCaptureAction.OpenWith;
            }
            set
            {
                switch (value)
                {
                    case PostCaptureAction.DoNothing:
                        doNothingRadioButton.Checked = true;
                        break;
                    case PostCaptureAction.GoToLastScreenshot:
                        goToRadioButton.Checked = true;
                        break;
                    case PostCaptureAction.OpenWith:
                        openWithRadioButton.Checked = true;
                        break;
                }
            }
        }

        public CaptureMethod CaptureMethod
        {
            get
            {
                if (primaryScreenRadioButton.Checked)
                    return CaptureMethod.PrimaryScreen;
                else if (mouseHoveredScreenRadioButton.Checked)
                    return CaptureMethod.MouseHoveredScreen;

                return CaptureMethod.AllScreens;
            }
            set
            {
                switch (value)
                {
                    case CaptureMethod.AllScreens:
                        allScreensRadioButton.Checked = true;
                        break;
                    case CaptureMethod.MouseHoveredScreen:
                        mouseHoveredScreenRadioButton.Checked = true;
                        break;
                    case CaptureMethod.PrimaryScreen:
                        primaryScreenRadioButton.Checked = true;
                        break;
                }
            }
        }

        public EncoderParameters EncoderParameters
        {
            get;
            set;
        }

        private void InitializeApplication()
        {
            FillControls();
        }


        private void FillControls()
        {
            FillImageFormats();
        }

        private void FillImageFormats()
        {
            imageFormatsComboBox.DataSource = SharkApp.Instance.Codecs;
        }

        private void SaveSettings()
        {
            var i = SharkApp.Instance;

            i.OutputDirectory = OutputDirectory;
            i.CodecInfo = CodecInfo;
            i.RunOnStartup = RunOnStartup;
            i.CaptureMethod = CaptureMethod;
            i.OpenWith = OpenWith;
            i.PostCaptureAction = PostCaptureAction;
            i.PreviewBeforeSave = PreviewBeforeSave;
            i.JpegQuality = JpegQuality;
            i.SaveSettings();
        }

        private void LoadSettings()
        {
            var i = SharkApp.Instance;
            i.LoadSettings();
            
            OutputDirectory = i.OutputDirectory;
            CodecInfo = i.CodecInfo;
            RunOnStartup = i.RunOnStartup;
            CaptureMethod = i.CaptureMethod;
            OpenWith = i.OpenWith;
            PostCaptureAction = i.PostCaptureAction;
            PreviewBeforeSave = i.PreviewBeforeSave;
            JpegQuality = i.JpegQuality;
        }

        private void CreateHotkeys()
        {
            fPrintScreen = new GlobalHotkey(GlobalHotkey.NOMOD, Keys.PrintScreen, this);
            fAltPrintScreen = new GlobalHotkey(GlobalHotkey.ALT, Keys.PrintScreen, this);
        }

        private void RegisterHotkeys()
        {
            fPrintScreen.Register();
            fAltPrintScreen.Register();
        }

        private void HandleHotkey(Keys key,int modifier)
        {
            Execute(modifier == GlobalHotkey.ALT);
        }

        private void Execute(bool activeWindowOnly)
        {
            Image i = SharkApp.Instance.CaptureScreenshot(activeWindowOnly);
            
            if (null == i)
            {
                ShowSplashForm("There is no active window at the moment!", Color.DarkRed);
                return;
            }

            if (SharkApp.Instance.PreviewBeforeSave)
            {
                ShowSplashForm("Screenshot captured. Showing preview...", SystemColors.AppWorkspace);

                ShowPreviewForm(i);                
            }
            else
            {
                SaveImage(i);
                
                i.Dispose();
            }
        }

        private void SaveImage(Image image)
        {
            try
            {
                SharkApp.Instance.SaveImageToOutputDirectory(image, SharkApp.GetNewFileName());

                ShowSplashForm("Screenshot saved as " + Path.GetFileName( SharkApp.Instance.LastScreenshot), SystemColors.AppWorkspace);

                SharkApp.Instance.DoPostCaptureAction();
            }
            catch (Exception ex)
            {
                ShowSplashForm("Error: " + ex.Message, Color.DarkRed);
            }

        }

        private void ShowPreviewForm(Image image)
        {
            var fPreviewForm = new PreviewForm()
            {
                PreviewImage = image
            };

            fPreviewForm.FormClosed += new FormClosedEventHandler(PreviewForm_FormClosed);
            fPreviewForm.ContinueClicked += new EventHandler(PreviewForm_ContinueClicked);
            fPreviewForm.Show();
            
            fPreviewFormList.Add(fPreviewForm);
        }

        private void ShowSplashForm(String text, Color fillColor)
        {
            if (null != fSplashForm)
            {
                fSplashForm.Close();
            }

            fSplashForm = new SplashForm()
            {
                FillColor = fillColor
            };

            fSplashForm.FormClosed += new FormClosedEventHandler(SplashForm_FormClosed);
            fSplashForm.LabelText = text;
            fSplashForm.Show();
            
        }

        private void PreviewForm_ContinueClicked(object sender, EventArgs e)
        {
            var pf = sender as PreviewForm;

            var i = pf.GetResultImage();

            SaveImage(i);
        }

        private void PreviewForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            var pf = sender as PreviewForm;
            
            fPreviewFormList.Remove(sender as PreviewForm);
        }

        void SplashForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            fSplashForm = null;
        }

        private void UnregisterHotkeys()
        {
            fPrintScreen.Unregister();
            fAltPrintScreen.Unregister();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            RegisterHotkeys();

            versionLabel.Text = Application.ProductVersion;
        }


        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            UnregisterHotkeys();
            SaveSettings();

            notifyIcon.Visible = false;

            if (null != fSplashForm)
                fSplashForm.Dispose();

            foreach (var f in fPreviewFormList)
                f.Dispose();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == GlobalHotkey.WM_HOTKEY_MSG_ID)
            {
                Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
                int modifier = (int)m.LParam & 0xFFFF;

                HandleHotkey(key,modifier);
            }
            else if (m.Msg == SingleInstance.WM_SHOWFIRSTINSTANCE)
            {
                Show();
            }

            base.WndProc(ref m);
        }

        private void browseButton_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
                folderTextBox.Text = folderBrowserDialog.SelectedPath;
        }

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Show();
            this.Activate();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                this.Hide();
            }
        }

        private void contextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Show();
        }

        private void imageFormatsComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            advancedButton.Enabled = SharkApp.IsEncoderSupported(CodecInfo, System.Drawing.Imaging.Encoder.Quality);
        }

        private void imageFormatsComboBox_Format(object sender, ListControlConvertEventArgs e)
        {
            ImageCodecInfo codec = e.ListItem as ImageCodecInfo;

            e.Value = String.Format("{0} - {1}", codec.FormatDescription, codec.CodecName);

        }

        private void cancelbutton_Click(object sender, EventArgs e)
        {
            Hide();
        }

        private void applyButton_Click(object sender, EventArgs e)
        {
            SaveSettings();
            Hide();
        }

        private void advancedButton_Click(object sender, EventArgs e)
        {
            using (var f = new AdvancedForm())
            {
                f.JpegQuality = JpegQuality;

                if (f.ShowDialog() == DialogResult.OK)
                {
                    JpegQuality = f.JpegQuality;    
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
        }

        private void notifyIcon_Click(object sender, EventArgs e)
        {

        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void goToButton_Click(object sender, EventArgs e)
        {
            var dir = folderTextBox.Text;
            
            if(Directory.Exists(dir))
            {
                SharkApp.GoToDirectoryInExplorer(dir);                
            }
            else
            {
                MessageBox.Show("Directory doesn't exist!","Error",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            }
        }

        private void goToToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SharkApp.Instance.GoToOutputDirectory();
        }

        private void openWithRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            openWithTextBox.Enabled = openWithRadioButton.Checked;
            openWithBrowseButton.Enabled = openWithRadioButton.Checked;
        }

        private void openWithBrowseButton_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                openWithTextBox.Text = openFileDialog.FileName;
            }
        }

 
        private void MainForm_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible)
                LoadSettings();
        }
    }
}
